/**
 * @author caojj
 * @version 1.0.2.2
 * @require Misc.Position
 * 
 * @tip: expando 在FF中不要用setAttribute 和 getAttribute，直接用“=”号赋值;
 * @需要改进: 是否考虑一个dragable一次带动多个moveable，通常可以把多个moveable放进一个div中来解决。
 * @需要改进: 改为对象形式，用prototype，已加入$startDrag, $endDrag方法;	** 不一定适用 @20080714
 * @plan
 * 			* 拖入IFrame等框架时引起的拖动中断
 * 			* 命名规范整理
 * @history
 * 			1.0.0.2	# 没有传递domMoveable时domMoveable与domDragable相同	@20080414
 * 			1.0.0.3	# IE下由于鼠标拖动时触发select导致拖动中断(没有完全解决) @20080414
 * 			1.0.1.0	# IE / FF 页面内容不满时鼠标拖动划出domMoveable后无效的问题 @20080714
 * 					+ 拖拽时与鼠标的偏移量offsetPos @20080714
 * 					+ 组件文档 及 新范例 @20080714
 * 					+ 加入调用绑定在DOM上的拖拽交互事件 @20080714
 * 			1.0.1.5 # 解决由于margin造成的位置计算问题 @20080714
 * 			1.0.1.6	# 拖拽时会选中页面内容的问题 @20080714
 * 			1.0.2.0 + 允许拖动范围的设定 miscParam.scale 或者 scale.scaleDom @20081125
 * 
 * @usage
 * 		var domMoveable = document.getElementById("domMoveable");
 * 		domMoveable.$endDrag = function(evt) {
 * 			alert("I'm end");
 * 		}
 * 		var domDragable = document.getElementById("domDragable");
 * 
 * 		FWK.Util.Dragable.apply(domDragable, [domMoveable, {x:3, y:3}, true]);
 * 
 * 		-------------------------
 * 		补充说明如下：
 * 		domDragable 为触发拖动的DOM，如窗口标题栏；
 * 		domMoveable 由拖动事件触发带动的DOM，如窗口本身；
 * 		如不传 domMoveable、则 domMoveable 等同于 domDragable；
 * 
 * 		有时候不设置偏移量 拖动中的DOM会把鼠标挡住，从而触发不了相应的鼠标事件（IE6中设为3比较合适）；
 * 
 * 		autoFireEvent设为true时会自动触发 domDragable、domMoveable 的 $startDrag 和 $endDrag事件；
 * 		autoFireEvent如为function，则会尝试触发 autoFireEvent(evt, domDragable, domMoveable)函数；
 */

/*
 * 定义命名空间
 */
try {
	if(!FWK.Util){
		throw "ns";
	}
} catch (ex) {
	try{FWK}catch(e){FWK={}}
	FWK.Util = {}
}

/**
 * 使DOM可以拖拽 详细用法看上面的@usage
 * @param {DOM} domMoveable
 * @param {Object} offsetPos
 * @param {Boolean} autoFireEvent
 */
FWK.Util.Dragable=function(domMoveable, offsetPos, autoFireEvent, miscParam){
	var domDragable = this;
	var domMoveable = domMoveable?domMoveable:this;
	
	var offsetPos = offsetPos?offsetPos:{x:0, y:0};
	
	if (miscParam) {
		if (miscParam.scale) {
			this.scale = miscParam.scale;
		}
		if (miscParam.scaleDom) {
			this.scale = getScale(miscParam.scaleDom);
		}
		if (miscParam.mode) {
			this.mode = "relative";
		}
	}
	
	function getScale(dom) {
		var crood = FWK.getDomCoord(miscParam.scaleDom);
		domDragable.scale = {x:crood.x, y:crood.y, w:dom.offsetWidth-domDragable.offsetWidth, h:dom.offsetHeight-domDragable.offsetHeight};
		return domDragable.scale;
	}
	
	//# IE下由于鼠标拖动时触发select导致拖动中断
//	domDragable.onselectstart = retFalse;
//	domMoveable.onselectstart = retFalse;
	
	this.beginDrag=function(ev) {
		domDragable.eventStatus = "beginDrag";		//autoFireEvent调用时用到
//		if (offsetPos) {	//可能将页面已有cursor样式覆盖
//			document.body.style.cursor = "move";
//		}
		
//		var domDragable = this;
		domDragable.setAttribute("_dragStatus", "start");
		var evt = ev||window.event;
		var mousePos = FWK.getMsCoord(evt);
//		var domMoveablePos = getPosition(domMoveable);
		domDragable._mousePos=mousePos;

		try{
			document.attachEvent("onmouseup", domDragable.endDrag);
			document.attachEvent("onmousemove", domDragable.doMove);
			
			if(!document.onselectstart) {
				document.onselectstart = retFalse;
			}
			
			domDragable.onselectstart = retFalse;
			domMoveable.onselectstart = retFalse;
		}catch(ex){
			window.addEventListener("mouseup", domDragable.endDrag, false);
			window.addEventListener("mousemove", domDragable.doMove, false);
			
			document.body.style.MozUserSelect = "none";
			domDragable.style.MozUserSelect = "none";
			domMoveable.style.MozUserSelect = "none";
		}
		
		try{
			//在外部定义
			if (autoFireEvent) {
				domDragable.$startDrag(evt);
				if (domDragable != domMoveable) {
					domMoveable.$startDrag(evt);
				}
				if (typeof(autoFireEvent)=="function") {
					autoFireEvent(evt, domDragable, domMoveable, this);
				}
			}
		}catch(ex){}
	}
	this.endDrag = function(ev){
		domDragable.eventStatus = "endDrag";
		
//		if (offsetPos) {
//			document.body.style.cursor = "";
//		}
		
		var evt = ev||window.event;
//		var domDragable = this;
		domDragable.removeAttribute("_dragStatus");
		var mousePos = FWK.getMsCoord(evt);
		
		try{
			document.detachEvent("onmouseup", domDragable.endDrag);
			document.detachEvent("onmousemove", domDragable.doMove);
			
			if(document.onselectstart == retFalse) {
				document.onselectstart = "";
			}
			
			domDragable.onselectstart = "";
			domMoveable.onselectstart = "";
		}catch(ex){
			window.removeEventListener("mouseup", domDragable.endDrag, false);
			window.removeEventListener("mousemove", domDragable.doMove, false);
			
			document.body.style.MozUserSelect = "";
			domDragable.style.MozUserSelect = "";
			domMoveable.style.MozUserSelect = "";
		}
		
		try{
			//在外部定义
			if (autoFireEvent) {
				domDragable.$endDrag(evt);
				if (domDragable != domMoveable) {
					domMoveable.$endDrag(evt);
				}
				if (typeof(autoFireEvent)=="function") {
					autoFireEvent(evt, domDragable, domMoveable, this);
				}
			}			
		}catch(ex){}
	}
	this.doMove = function(ev){
		domDragable.eventStatus = "doMove";
		window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();		//清除选择
//		event.cancelBubble = true;
//		var domDragable = this;
//		var domMoveable = this.domMoveable;
		var _dragStatus = domDragable.getAttribute("_dragStatus");
		var _mousePos = domDragable._mousePos;
		if(_dragStatus&&_dragStatus=="start"&&_mousePos) {
			var evt = ev||window.event;
			var mousePos = FWK.getMsCoord(evt);
			var domMoveablePos = FWK.getDomCoord(domMoveable);
			
			if (offsetPos) {
				mousePos.x += offsetPos.x;
				mousePos.y += offsetPos.y;
			}
			
			// 由于margin造成的偏移量 border 与 padding 没有问题		
			
			function getStyleOffset() {
				var marginLeft = 0;
				var marginTop = 0;
				
				if (!!document.all) {
					marginLeft = parseInt(domMoveable.currentStyle.marginLeft);
					marginTop = parseInt(domMoveable.currentStyle.marginTop);
	
				} else if (window.getComputedStyle) {
					marginLeft = parseInt(window.getComputedStyle(domMoveable, "").getPropertyValue("margin-left"));
					marginTop = parseInt(window.getComputedStyle(domMoveable, "").getPropertyValue("margin-top"));
				}
				
				styleOffset = {
					x : marginLeft?marginLeft:0,
					y : marginTop?marginTop:0
				}
				
				return styleOffset;
			}

			var styleOffset = getStyleOffset();	
						
			var _offsetPos = {x:mousePos.x - _mousePos.x - styleOffset.x, y:mousePos.y - _mousePos.y - styleOffset.y}
			
			var _posX = domMoveablePos.x + _offsetPos.x;
			var _posY = domMoveablePos.y + _offsetPos.y;
			
			if (miscParam&&miscParam.scaleDom) {
				this.scale = getScale(miscParam.scaleDom);
			}
			
			domDragable._mousePos=mousePos;
			
			if (this.scale) {
				if (_posX<this.scale.x) {
					_posX=this.scale.x;
					
					domDragable._mousePos.x=_posX+(domDragable.offsetWidth/2);			//拖出外框时不记录鼠标
				} else if (_posX>(this.scale.x + this.scale.w)) {
					_posX=this.scale.x + this.scale.w;
					
					domDragable._mousePos.x=_posX+(domDragable.offsetWidth/2);
				}
				
				if (_posY<this.scale.y) {
					_posY=this.scale.y;
					
					domDragable._mousePos.y=_posY+(domDragable.offsetHeight/2);
				} else if (_posY>(this.scale.y + this.scale.h)) {
					_posY=this.scale.y + this.scale.h;
					
					domDragable._mousePos.y=_posY+(domDragable.offsetHeight/2);
				}
			}


			if (domDragable.mode=="relative") {
//				debugger;
				domMoveable.style.left = _posX - this.scale.x + "px";
				domMoveable.style.top = _posY - this.scale.y + "px";
			} else {
				domMoveable.style.left = _posX + "px";
				domMoveable.style.top = _posY + "px";
			}			
						
//			domMoveable.style.left = domMoveablePos.x + _offsetPos.x + "px";
//			domMoveable.style.top = domMoveablePos.y + _offsetPos.y + "px";
			
			
			
			//在外部定义
			try {
				if (autoFireEvent) {
					domDragable.$doMove(evt);
					if (domDragable != domMoveable) {
						domMoveable.$doMove(evt);
					}
					if (typeof(autoFireEvent)=="function") {
						autoFireEvent(evt, domDragable, domMoveable, this);
					}
				}
			}catch(ex){}
		}
	}
	
	/*
	 * 禁用推拽
	 */
	this.dragDisable = function(){
//		domMoveable.style.position="absolute";
		domDragable.style.cursor="auto";
		
		try{
			domDragable.detachEvent("onmousedown", this.beginDrag);
			domDragable.detachEvent("onmouseup", this.endDrag);
			document.detachEvent("onmouseup", domDragable.endDrag);
			document.detachEvent("onmousemove", domDragable.doMove);
		}catch(ex){
			domDragable.removeEventListener("mousedown", this.beginDrag, false);
			domDragable.removeEventListener("mouseup", this.endDrag, false);
			window.removeEventListener("mouseup", domDragable.endDrag, false);
			window.removeEventListener("mousemove", domDragable.doMove, false);
		}
	}
	
	/*
	 * 启用推拽
	 */
	this.dragEnable = function() {
//		domMoveable.style.position="absolute";
		domDragable.style.cursor="move";
		
		try {
			domDragable.attachEvent("onmousedown", this.beginDrag);
			domDragable.attachEvent("onmouseup", this.endDrag);
		} catch (ex) {
			domDragable.addEventListener("mousedown", this.beginDrag, false);
			domDragable.addEventListener("mouseup", this.endDrag, false);
		}
	}
	
	//构造
	{
		domMoveable.style.position= (this.mode && this.mode == "relative") ? "relative" : "absolute";
		this.dragEnable();
	}
	
	function retFalse() {
		return false;
	}
}